#一、 基础条件查询
# 1 基本查询
# get 查询单一结果，如果不存在会抛出模型类。DoesNotExist异常。
from book.models import BookInfo, PeopleInfo
# 查询 id=1 的图书
BookInfo.objects.get(id=1)
# 如果  id=5 不存在， 抛异常DoesNotExis
BookInfo.objects.get(id=5)


# all 查询多个结果
BookInfo.objects.all()

#查询图书总数量
BookInfo.objects.count()
#查询人物总数量
PeopleInfo.objects.count()

# 2 过滤查询
"""
实现SQL中的whele功能， 包括：
    - filter过滤出多个结果
    - exclude排除掉符合条件剩下的结果
    - get过滤单一结果
对过滤条件的使用， 上述三个方法相同， 故仅以filte进行讲解。

过滤条件的表达语法如下：
     属性名称__比较运算符=值
     属性名称和比较运算符间使用两个下划线， 所以属性名不能包括多个下划线
"""

#1）相等 -- exact:表示判等。
# 查询编号为1的图书
BookInfo.objects.get(id__exact=1)
# 简写
BookInfo.objects.get(id=1)
# pk: primary(主要的) key(键)
BookInfo.objects.get(pk=1)

#2) 模糊查询--contains: 是否包含。
#  查询书名包含‘传’的图书
BookInfo.objects.filter(name__contains='传')

# startswith、endswith:以指定值开头或结尾
#查询书名以‘部’结尾的图书
BookInfo.objects.filter(name__endswith='部')
#查询书名以‘射’结尾的图书
BookInfo.objects.filter(name__startswith='射')


#3） 空查询 -- isnull: 是否为null.
#查询书名为空的图书
BookInfo.objects.filter(name__isnull=True)
#查询书名不为空的图书
BookInfo.objects.filter(name__isnull=False)


#4） 查询范围 -- in: 是否包含在范围内
# 查询编号id 为 1，，3，5 的图书
BookInfo.objects.filter(id__in=[1, 3, 5])

#5)比较查询
"""
   gt大于(greater then)
   gte大于等于(greater then equal)
   lt小于(less then)
   lte小于等于(less then equal)
"""
#查询编号id大于3的图书
BookInfo.objects.filter(id__gt=3)
BookInfo.objects.filter(id__lte=2)


# 不等于的运算符， 使用exclude()过滤器
#查询编号不等于3的图书
BookInfo.objects.exclude(id=3)


#6) 日期查询
# year month day week_day hour minute second: 对日期时间类型的属性进行运算
#查询pub_date 时间1980年发表的书
BookInfo.objects.filter(pub_date__year=1980)

#查询pub_date 时间1990年1月1日发表的书
BookInfo.objects.filter(pub_date__gt='1990-1-1')


"""
1. F对象
     之前的查询都是对象的属性与常量值比较，两个属性怎么比较呢？ 答：使用F对象， 被定义在django.db.models中。
     
     
     语法如下：
     F（属性名）
     例：查询阅读量大于等于评论量的图书
     """
# 导包
from django.db.models import F, Q
# 查询 阅读量readcount 大于等于评论量commentcount的图书
BookInfo.objects.filter(readcount__gte=F('commentcount'))

#可以在F对象上使用算术运算
#查询 阅读量readcount 大于等于 2倍评论量commentcount的图书
BookInfo.objects.filter(readcount__gte=F('commentcount')*2)

"""
2.Q对象
   多个过滤器逐个调用表示逻辑与关系，同sql语句中where部分and关键字
"""

#查询阅读量readcount 大于20， 并且编号id小于3的图书
BookInfo.objects.filter(readcount__gt=20, id__lt=3)
#查询阅读量readcount 大于20， 并且编号id小于3的图书,只能使用Q对象实现
BookInfo.objects.filter(Q(readcount__gt=20) | Q(id__lt=3))


#查询编号id不等于3的图书
#   Q对象前可以使用~操作符， 表示非not
BookInfo.objects.filter(~Q(id=3))
#查询编号id不等于1和3的图书
BookInfo.objects.filter(~Q(id__in=[1, 3]))

#三、聚合函数和降序函数
#1、 使用aggregate()过滤器调用聚合函数，聚合函数： Aug平均， Count数量， Max最大， Min最小，Sum求和
from django.db.models import Sum, Max, Avg, Count, Min
# 查询图书的总阅读量readcount
BookInfo.objects.aggregate(Sum('readcount'))
# 查询图书的最大评论量commentcount
BookInfo.objects.aggregate(Min('commentcount'))
#查询图书平均阅读量readcount
BookInfo.objects.aggregate(Avg('readcount'))

#2.排序
# 使用order_by对结果进行排序
# 默认 按照主键 升序排序
BookInfo.objects.all()
# 按照给定的字段名阅读量readcount（列名）进行 升序排序
BookInfo.objects.all().order_by('readcount')

#按照给定的字段名评论量commentcount列名）进行 降序排序
BookInfo.objects.all().order_by('-commentcount')
#按照给定的 字段名 出版日期 pub_date(列名）进行升序/降序排序
BookInfo.objects.all().order_by('pub_date')

#四、级联查询，# 关联查询
#1，关联查询
#1.1由一到多的访问语法： 一对应的模型类对象。多对应的模型类小写_set
#查询书籍id为1的所有人物信息
#一对应的模型类对象
book = BookInfo.objects.get(id=1)
#多对应的模型类小写_set,通过all()返回所有人物
book.peopleinfo_set.all()

#查询书籍名称为name'雪山飞狐'的所有人物信息
book = BookInfo.objects.get(name='雪山飞狐')
book.peopleinfo_set.all()

#1.2 由多到一的访问语法：多对应的模型类对象，多对应的模型类中的关系类属性名
##查询人物id为1的书籍信息
#多对应的模型类对象
people = PeopleInfo.objects.get(id=1)
#多对应的模型类中的关系类属性名
people.book

#1.3访问一对应的模型类关联对象的id语法：多对应的模型类对象。关联类属性_id
#查询id=1的人物所属图书id
people.book_id

#查询人物名字name为'虚竹'的书籍信息
people = PeopleInfo.objects.get(name='虚竹')
people.book

#查询图书，要求图书 人物name为“郭靖“
book = BookInfo.objects.get(peopleinfo__name='郭靖')

#查询图书，要求图书 人物的描述description包含”八“
books = BookInfo.objects.filter(peopleinfo__description__contains='八')


#查询书名name为”天龙八部“的所有人物
peoples = PeopleInfo.objects.filter(book__name='天龙八部')

#查询阅读量readcount大于30的所有人物
peoples = PeopleInfo.objects.filter(book__readcount__gt=30)
